from sqlalchemy.future import select
from fastapi import Request, HTTPException
import time
import json

from utils.jwtToken import generate_token
from core.Config import settings
from core.Log import log_admin_event
from database.mysql import AsyncSessionLocal
import models.admin.user.user as UserModel
from models.admin.user.third_user import Game_Third_User

class ThirdServer:
  def __init__(self):
    self.name = 'ThirdServer'

  # 异步静态方法
  @staticmethod
  async def get_user_info(platform: str, params: dict, request: Request):
    if platform == "Wechat":
      from .Wechat import Wechat
      wechat = Wechat()
      userInfo = await wechat.get_user_info(params['code'])
    else:
      userInfo = {
        "openid": "oCtBs1tZIPG8aPn9UueAwZwRlEJ4",
        "nickname": "彭飞2",
        "sex": 0,
        "language": "",
        "city": "",
        "province": "",
        "country": "",
        "headimgurl": "https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKDicf5o1DPnLLEZKcib4bbjpvALuCsVuVnv9CAN4SUqv4lbWZFo02JyaOcJ1kY4VfHjHNctaqDt3HA/132",
        "privilege": []
      }
    return_userinfo  = await ThirdServer.save_user_info(platform, userInfo, request)
    return return_userinfo

  # 获取用户信息，存入数据库
  @staticmethod
  async def save_user_info(platform: str, user_info: dict, request: Request):
    isBindUser = await ThirdServer.check_user_exist(platform, user_info, request)
    if not isBindUser:
      async with AsyncSessionLocal() as session:
        try:
          username = user_info["openid"][:10]
          password = user_info["openid"]
          email = username + f"@{platform}.com"
          nickname = user_info["nickname"]
          joinip = request.client.host
          join_time = time.time() 


          add_user = UserModel.Game_User(
            username=username,
            password=password,
            email=email,
            nickname=nickname,
            joinip=joinip,
            jointime=join_time,
            type=UserModel.UserType.THIRD_PARTY
          )
          session.add(add_user)
          await session.commit()
          user_id = add_user.id

          Third_User = Game_Third_User(
            user_id=user_id,
            platform=platform,
            openid=user_info['openid'],
            unionid=user_info.get('unionid', '')
          )
          session.add(Third_User)
          await session.commit()
          token = generate_token(add_user.username, settings.SESSION_MAX_AGE)
         
          redis_user = UserModel.redis_user(
              id=user_id,
              nickname=nickname,
              username=username,
              group_id=1,
              gender=add_user.gender,
              bio="",
              money=0,
              score=0,
              level=0,
              mobile="",
              third_user=Third_User.model_dump() if hasattr(Third_User, 'model_dump') else Third_User
          )
          # 创建一个return_user变量，将redis_user的值赋给return_user，然后再将token的值赋给return_user
          return_user = redis_user.__dict__.copy()
          return_user["accessToken"] = token["accessToken"]
          return_user["refreshToken"] = token["refreshToken"]
          return_user["expires"] = token["expires"]
          await request.app.state.cache.set(f"gameuser:{username}", json.dumps(redis_user))
          await ThirdServer.get_user_auths(platform, username, 1, request)
          return return_user
        except Exception as e:
          log_admin_event(f"third_login error 第三方登录失败：{e}")
          raise HTTPException(status_code=400, detail=e)
    else:
      return isBindUser
    
  # 判断用户是否存在
  @staticmethod
  async def check_user_exist(platform: str, user_info: dict, request: Request) -> bool:
    username = user_info["openid"][:10]
    # 先判断redis中是否存在
    user = await request.app.state.cache.get(f"gameuser:{username}")
    if user:
      user = json.loads(user)
      return user
    else:
      # 创建主用户，绑定第三方用户
      async with AsyncSessionLocal() as session:
        try:
          openid = user_info["openid"]
          Third_User = select(Game_Third_User).where(Game_Third_User.openid == openid).where(Game_Third_User.platform == platform)
          result = await session.exec(Third_User)
          obj = result.scalars().first()

          if obj:
            game_user = select(UserModel.Game_User).where(UserModel.Game_User.id == obj.user_id)
            result = await session.exec(game_user)
            user = result.scalars().first()
            token = generate_token(user.username, settings.SESSION_MAX_AGE)
            redis_user = UserModel.redis_user(
                id=user.id,
                nickname=user.nickname,
                username=user.username,
                group_id=user.group_id,
                gender=user.gender,
                bio=user.bio,
                money=user.money,
                score=user.score,
                level=user.level,
                mobile=user.mobile,
                third_user=obj.model_dump() if hasattr(obj, 'model_dump') else obj
            )
            # 创建一个return_user变量，将redis_user的值赋给return_user，然后再将token的值赋给return_user
            return_user = redis_user.__dict__.copy()
            return_user["accessToken"] = token["accessToken"]
            return_user["refreshToken"] = token["refreshToken"]
            return_user["expires"] = token["expires"]
            await request.app.state.cache.set(f"gameuser:{user.username}", json.dumps(redis_user))
            await ThirdServer.get_user_auths(platform, user.username, user.group_id, request)
            return return_user
          return obj
        except Exception as e:
          log_admin_event(f"third_login error 第三方用户信息入库失败：{e}")
          raise HTTPException(status_code=400, detail=e)


  # 根据用户角色组，获取用户权限,存入redis
  @staticmethod
  async def get_user_auths(platform: str, username: str, group_id:int, request: Request):
    async with AsyncSessionLocal() as session:
      # 根据用户角色组，获取用户权限
      statement = select(UserModel.Game_Group_Rule_Link).where(UserModel.Game_Group_Rule_Link.group_id == group_id)
      result = await session.exec(statement)
      rules = result.scalars().all()
      rule_ids = [rule.rule_id for rule in rules]

      # 根据权限id，获取权限
      statement = select(UserModel.Game_User_Rule.auths).where(UserModel.Game_User_Rule.id.in_(rule_ids)).where(UserModel.Game_User_Rule.menu_type == UserModel.MenuTypeEnum.BUTTON)
      result = await session.exec(statement)
      user_rules = result.scalars().all()
      await request.app.state.cache.set(f"gameuser:{username}_auths", json.dumps(user_rules))
      return user_rules